import fs from "fs";
import { parse } from "@babel/parser";
import * as t from "@babel/types";
import _traverse from "@babel/traverse";
const traverse = _traverse.default;
import _generate from "@babel/generator";
const generate = _generate.default;
import path from "path";
import { globSync } from "glob";
import inquirer from "inquirer";
import { exec } from "child_process";

let fileCount;
const extractObj = {};
let sourceFile;
const supportFileTypes = [".ts", ".js", ".jsx", ".tsx"];
let matchReg;
let hasChange = false;
let maxIndex = 0;

(async function () {
    const data = fs.readFileSync("script/config/tr_extract.json")
    const config = JSON.parse(data)
    if (config.mat.length !== 2) {
        return console.err(`必须是成对的定界符：${config.mat}`)
    }
    matchReg = new RegExp(`\\${config.mat[0]}(.+?)\\${config.mat[1]}`)
    const langs = fs.readdirSync("src/lang/lan").map(lang => path.basename(lang, ".json"))
    const { files, lan } = await inquirer.prompt([{ type: "input", name: 'files', message: '输入你要提取转换的文件：' }, { type: "list", name: "lan", message: "选择语言", choices: langs },])
    const paths = globSync(files, { ignore: config.exclude });
    fileCount = paths.length;

    if (fileCount === 0) {
        return console.log(`查找的文件不存在：${files}`)
    }
    config.lan = lan;
    sourceFile = fs.readFileSync(`src/lang/lan/${lan}.json`)
    maxIndex = Object.values(JSON.parse(sourceFile)[config.field] || []).length;

    paths.forEach(_path => {
        if (!supportFileTypes.includes(path.extname(_path))) {
            fileCount--;
            console.log(`文件类型不支持：${_path}`);
        } else {
            hasChange = false;
            const res = fs.readFileSync(_path)
            traverser(res.toString(), _path, config)
        }
    })
})();

function traverser(code, _path, config) {
    let isImportT = false;

    const ast = parse(code, { sourceType: "module", plugins: ["jsx", "typescript"] });

    traverse(ast, {
        ImportDeclaration(path) {
            if (path.node?.source?.value.includes("/lang") && path.node?.specifiers?.some(a => a.imported?.name === "t")) {
                isImportT = true;
            }
        },
        JSXText(path) {
            if (matchReg.test(path.node.value)) {
                maxIndex++;
                const callExpression = t.callExpression(
                    t.identifier("t"), // 函数名 t
                    [t.stringLiteral(`${config.field}.a_${maxIndex}`)] //  "auto.a_1"
                );

                extractObj[`a_${maxIndex}`] = path.node.value?.match(matchReg)[1];
                path.replaceWith(t.jsxExpressionContainer(callExpression));
                hasChange = true;
            }
        },
        StringLiteral(path) {
            if (matchReg.test(path.node.value)) {
                maxIndex++;
                extractObj[`a_${maxIndex}`] = path.node.value?.match(matchReg)[1];
                const callExpression = t.callExpression(
                    t.identifier("t"),
                    [t.stringLiteral(`${config.field}.a_${maxIndex}`)]
                );
                if (path.parent.type === "JSXAttribute") {
                    path.replaceWith(t.jsxExpressionContainer(callExpression));
                } else {
                    path.replaceWith(callExpression);
                }
            }
        }
    })
    if (!isImportT && hasChange) {
        const lastIndex = ast.program.body.findLastIndex(node => t.isImportDeclaration(node));
        const importDeclaration = t.importDeclaration(
            [t.importSpecifier(t.identifier('t'), t.identifier('t'))], // importSpecifier 作为数组
            t.stringLiteral("@/lang") // source 属性
        );
        ast.program.body.splice(lastIndex + 1, 0, importDeclaration);
    }

    const result = generate(ast, {
        sourceMaps: false,
        sourceFileName: path.basename(_path)
    }, code);

    // 写入转化文件
    if (hasChange) {
        try {
            fs.writeFileSync(_path, result.code);
            console.log(`文件转换成功：${path.resolve(_path)}`)
        } catch (err) {
            console.error(`文件转换失败：${path.resolve(_path)}`, err);
        }
    }

    fileCount--;
    // 写入语言文件
    if (fileCount === 0) {
        const mergeObj = Object.assign(JSON.parse(sourceFile)[config.field] || {}, extractObj);
        sourceFile = Object.assign(JSON.parse(sourceFile), { [config.field]: mergeObj });

        fs.writeFileSync(`src/lang/lan/${config.lan}.json`, JSON.stringify(sourceFile, null, 4));
        inquirer.prompt({ name: "isTranslate", type: "confirm", message: "执行完毕，是否需要自动翻译？", default: true }).then(res => {
            if (res.isTranslate) {
                exec(`node script/translate.cjs ${config.lan}`);
            }
        })
    }
}
